
#include "ST7735.h"


#define DELAY 0x80

// based on Adafruit ST7735 library for Arduino
static const uint8_t
init_cmds1[] =              // Init for 7735R, part 1 (red or green tab)
{
    15,                       // 15 commands in list:
    ST7735_SWRESET,   DELAY,  //  1: Software reset, 0 args, w/delay
    150,                    //     150 ms delay
    ST7735_SLPOUT,   DELAY,   //  2: Out of sleep mode, 0 args, w/delay
    255,                    //     500 ms delay
    ST7735_FRMCTR1, 3,        //  3: Frame rate ctrl - normal mode, 3 args:
    0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
    ST7735_FRMCTR2, 3,        //  4: Frame rate control - idle mode, 3 args:
    0x01, 0x2C, 0x2D,       //     Rate = fosc/(1x2+40) * (LINE+2C+2D)
    ST7735_FRMCTR3, 6,        //  5: Frame rate ctrl - partial mode, 6 args:
    0x01, 0x2C, 0x2D,       //     Dot inversion mode
    0x01, 0x2C, 0x2D,       //     Line inversion mode
    ST7735_INVCTR, 1,         //  6: Display inversion ctrl, 1 arg, no delay:
    0x07,                   //     No inversion
    ST7735_PWCTR1, 3,         //  7: Power control, 3 args, no delay:
    0xA2,
    0x02,                   //     -4.6V
    0x84,                   //     AUTO mode
    ST7735_PWCTR2, 1,         //  8: Power control, 1 arg, no delay:
    0xC5,                   //     VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
    ST7735_PWCTR3, 2,         //  9: Power control, 2 args, no delay:
    0x0A,                   //     Opamp current small
    0x00,                   //     Boost frequency
    ST7735_PWCTR4, 2,         // 10: Power control, 2 args, no delay:
    0x8A,                   //     BCLK/2, Opamp current small & Medium low
    0x2A,
    ST7735_PWCTR5, 2,         // 11: Power control, 2 args, no delay:
    0x8A, 0xEE,
    ST7735_VMCTR1, 1,         // 12: Power control, 1 arg, no delay:
    0x0E,
    ST7735_INVOFF, 0,         // 13: Don't invert display, no args, no delay
    ST7735_MADCTL, 1,         // 14: Memory access control (directions), 1 arg:
    ST7735_ROTATION,        //     row addr/col addr, bottom to top refresh
    ST7735_COLMOD, 1,         // 15: set color mode, 1 arg, no delay:
    0x05,
}                 //     16-bit color


void ST7735_spiWrite(uint8_t dt)
{
    // must use HAL_SPI_TransmitReceive - wait for whole byte transmission
    uint8_t rx;
    while(HAL_SPI_TransmitReceive(&hspi1, &dt, &rx, 1, HAL_MAX_DELAY) == HAL_BUSY);
}


void ST7735_WriteCommand(uint8_t cmd)
{
    ST7735_SELECT_COMMAND
    HAL_SPI_Transmit(&hspi1, &cmd, sizeof(cmd), HAL_MAX_DELAY);
}

void st7735_sendData(uint8_t dt)
{
    ST7735_SELECT_DATA
    ST7735_spiWrite(dt);
}

static void ST7735_WriteData(uint8_t* buff, uint16_t size)
{

    ST7735_SELECT_DATA
    HAL_SPI_Transmit(&hspi1, buff, size, HAL_MAX_DELAY);
}
static void ST7735_ExecuteCommandList(const uint8_t *addr)
{
    uint8_t numCommands, numArgs;
    uint16_t ms;

    numCommands = *addr++;
    while(numCommands--)
    {
        uint8_t cmd = *addr++;
        ST7735_WriteCommand(cmd);

        numArgs = *addr++;
        // If high bit set, delay follows args
        ms = numArgs & DELAY;
        numArgs &= ~DELAY;
        if(numArgs)
        {
            ST7735_WriteData((uint8_t*)addr, numArgs);
            addr += numArgs;
        }

        if(ms)
        {
            ms = *addr++;
            if(ms == 255) ms = 500;
            HAL_Delay(ms);
        }
    }
}

static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    // column address set
    ST7735_WriteCommand(ST7735_CASET);
    uint8_t data[] = { 0x00, x0 + ST7735_XSTART, 0x00, x1 + ST7735_XSTART };
    ST7735_WriteData(data, sizeof(data));

    // row address set
    ST7735_WriteCommand(ST7735_RASET);
    data[1] = y0 + ST7735_YSTART;
    data[3] = y1 + ST7735_YSTART;
    ST7735_WriteData(data, sizeof(data));

    // write to RAM
    ST7735_WriteCommand(ST7735_RAMWR);
}









// for ST7735R
void ST7735_InitR(void)
{
    //      ST7735_Select();
    //      ST7735_Reset();
          ST7735_ExecuteCommandList(init_cmds1);
    //      ST7735_ExecuteCommandList(init_cmds2);
    //      ST7735_ExecuteCommandList(init_cmds3);
    //      ST7735_Unselect();

}
// for ST7735B
void ST7735_InitB(void)
{
//      ST7735_Select();
//      ST7735_Reset();
//      ST7735_ExecuteCommandList(init_cmds1);
//      ST7735_ExecuteCommandList(init_cmds2);
//      ST7735_ExecuteCommandList(init_cmds3);
//      ST7735_Unselect();
}


void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color)
{
    if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT))
        return;

    ST7735_CS_ENABLE

    ST7735_SetAddressWindow(x, y, x + 1, y + 1);
    uint8_t data[] = { color >> 8, color & 0xFF };
    ST7735_WriteData(data, sizeof(data));

    ST7735_CS_DISABLE
}



void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
{
    // clipping
    if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) return;
    if((x + w - 1) >= ST7735_WIDTH) w = ST7735_WIDTH - x;
    if((y + h - 1) >= ST7735_HEIGHT) h = ST7735_HEIGHT - y;

    ST7735_CS_ENABLE
    ST7735_SetAddressWindow(x, y, x + w - 1, y + h - 1);

    uint8_t data[] = { color >> 8, color & 0xFF };
//      HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET);
    ST7735_SELECT_DATA
    for(y = h; y > 0; y--)
    {
        for(x = w; x > 0; x--)
        {
            HAL_SPI_Transmit(&hspi1, data, sizeof(data), HAL_MAX_DELAY);
        }
    }

    ST7735_CS_DISABLE
}

void ST7735_FillScreen(uint16_t color)
{
    ST7735_FillRectangle(0, 0, ST7735_WIDTH, ST7735_HEIGHT, color);
}







